package com.controller;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class BaseController {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private JmsMessagingTemplate jmsMessagingTemplate;

    private static final String startSalePromotionKey = "start/sale/promotion";
    private static final String promotionKey = "sale-promotion";
    private static final Snowflake snowflake = IdUtil.createSnowflake(1, 1);


    /**
     * 开始活动，将数据库查出来的上架库存信息存入redis
     *
     * @return 库存数量
     */
    @RequestMapping("start/sale/promotion")
    public Long startSalePromotion(Long stockInQuantity) {
        int promotionId = 1;
        //加锁且先查询库存是否已上架,防止多次(并发或重新上库存)请求上架库存,导致库存与订单销售数量不一致,导致超卖问题
        //比如一共三个请求同时过来处理,两个是上架库存,一个是下单.A,B线程上架库存,C线程下单
        //A上架库存完毕,C下单1单.按道理库存减了1,新增一个新订单
        //但是这时候B线程上架库存.这样库存又变回了活动刚开始时的库存数量,最后活动总销售数量就会多于此次活动设置的可销售库存数量
        synchronized (startSalePromotionKey) {
            Object stockInQuantityObj = redisTemplate.opsForHash().get(promotionKey, promotionId);
            if (stockInQuantityObj != null) {
                return Long.valueOf(stockInQuantityObj.toString());
            }
        }
        //从数据库中查这个活动的库存要上架多少
//        stockInQuantity = 1000L;
        redisTemplate.opsForHash().put(promotionKey, promotionId, stockInQuantity);
        return stockInQuantity;
    }


    @RequestMapping("buy")
    public String buy(Integer promotionId, Long userId) {
        Long increment = redisTemplate.opsForHash().increment(promotionKey, promotionId, -1);
        if (increment < 0) {
            return "库存不足,活动结束";
        }
        //用于记录用户下了几个活动订单,如果限制了某用户可以某活动下单多少件,可以在这个数据上进行控制
        userId = snowflake.nextId();//模拟用户id
        redisTemplate.opsForHash().put("order", userId, promotionId);
        //用于将用户的订单同步进mysql
        jmsMessagingTemplate.convertAndSend("order-mysql", userId + "=" + promotionId);
        return "购买成功";
    }

    @RequestMapping("stop")
    public String stop() {
        redisTemplate.delete(promotionKey);
        redisTemplate.delete("order");
        redisTemplate.delete("order-mysql");
        return "活动结束";
    }
}
